namespace feng3d
{
    /**
     * 加载类
     */
    export var loader: Loader;

    /**
     * 加载类
     */
    export class Loader
    {

        /**
         * 加载文本
         * @param url   路径
         */
        loadText(url: string, onCompleted?: (content: string) => void, onRequestProgress?: () => void, onError?: (e: Error) => void)
        {
            xmlHttpRequestLoad({ url: url, dataFormat: LoaderDataFormat.TEXT, onCompleted: <any>onCompleted, onProgress: onRequestProgress, onError: onError });
        }

        /**
         * 加载二进制
         * @param url   路径
         */
        loadBinary(url: string, onCompleted?: (content: ArrayBuffer) => void, onRequestProgress?: () => void, onError?: (e: Error) => void)
        {
            xmlHttpRequestLoad({ url: url, dataFormat: LoaderDataFormat.BINARY, onCompleted: <any>onCompleted, onProgress: onRequestProgress, onError: onError });
        }

        /**
         * 加载图片
         * @param url   路径
         */
        loadImage(url: string, onCompleted?: (content: HTMLImageElement) => void, onRequestProgress?: () => void, onError?: (e: Error) => void)
        {
            var image = new Image();
            image.crossOrigin = "Anonymous";
            image.onload = (event) =>
            {
                onCompleted && onCompleted(image);
            }
            image.onerror = (event) =>
            {
                debuger && console.error("Error while trying to load texture: " + url);
                //
                image.src = "";
                //
                var err = new Error(url + " 加载失败！");
                onError && onError(err);
            }
            image.src = url;
        }
    }

    loader = new Loader();

    interface LoadItem
    {
        url: string;
        dataFormat: string;
        onCompleted?: (content: string | ArrayBuffer) => void;
        onProgress?: (loaded: number, total: number) => void;
        onError?: (ev: Error) => void;
    }

    /**
     * 使用XMLHttpRequest加载
     * @param url           加载路径
     * @param dataFormat    数据类型
     */
    function xmlHttpRequestLoad(loadItem: LoadItem)
    {
        var request = new XMLHttpRequest();
        request.open('Get', loadItem.url, true);
        request.setRequestHeader("Access-Control-Allow-Origin", "*");
        request.responseType = loadItem.dataFormat == LoaderDataFormat.BINARY ? "arraybuffer" : "";
        request.onreadystatechange = onRequestReadystatechange(request, loadItem);
        request.onprogress = onRequestProgress(request, loadItem);
        request.send();
    }

    /**
     * 请求进度回调
     */
    function onRequestProgress(request: XMLHttpRequest, loadItem: LoadItem)
    {
        return (event: ProgressEvent) =>
        {
            loadItem.onProgress && loadItem.onProgress(event.loaded, event.total);
        }
    }

    /**
     * 请求状态变化回调
     */
    function onRequestReadystatechange(request: XMLHttpRequest, loadItem: LoadItem)
    {
        return (ev) =>
        {
            if (request.readyState == 4)
            {// 4 = "loaded"

                request.onreadystatechange = <any>null;

                if (request.status >= 200 && request.status < 300)
                {
                    var content = loadItem.dataFormat == LoaderDataFormat.TEXT ? request.responseText : request.response;
                    loadItem.onCompleted && loadItem.onCompleted(content);
                } else
                {
                    var err = new Error(loadItem.url + " 加载失败！");
                    loadItem.onError && loadItem.onError(err);
                    loadItem.onCompleted && loadItem.onCompleted(null);
                }
            }
        }
    }
}